﻿/*
 *	Copyright (c) 2009 Queensland University of Technology. All rights reserved.
 *	The QUT Bioinformatics Collection is open source software released under the 
 *	Microsoft Public License (Ms-PL): http://www.microsoft.com/opensource/licenses.mspx.
 */
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using QUT.Bio.Util;
using QUT.Bio.SilverMap.ObjectModel;

// TODO: disentangle from View (make an interface?) so we can build cleanly from scratch.

namespace QUT.Bio.SilverMap {
	public partial class SequenceSummaryTable : UserControl {
		private readonly ObservableCollection<SequenceSummary> visibleSequences = new ObservableCollection<SequenceSummary>();
		private MapControl map;

		public SequenceSummaryTable () {
			InitializeComponent();
		}

		public void Initialize (
			MapControl map
		) {
			this.map = map;

			// Suppress spurious drag effects that occur when user has clicked a column heading, it seems the button
			// down is propagated to the containing window but the button up is not.
			this.geneDetails.MouseLeftButtonDown += delegate( object sender, MouseButtonEventArgs args ) {
				args.Handled = true;
			};

			withinRadius.Click += delegate( object sender, RoutedEventArgs args ) {
				Refresh();
			};

			checkMarked.Click += delegate( object sender, RoutedEventArgs args ) {
				CheckMarkedRows();
			};

			uncheckMarked.Click += delegate( object sender, RoutedEventArgs args ) {
				UncheckMarkedRows();
			};

			geneDetails.ItemsSource = visibleSequences;

			centreOnSelection.Click += delegate( object sender, RoutedEventArgs args ) {
				CentreOnSelection();
			};

			Rebuild();
			map.View.ThresholdChanged += Refresh;
			map.Model.ReferenceSequenceUpdated += Refresh;
			map.Model.DataCollectionModified += Rebuild;
			map.Model.DataCollectionLoaded += Rebuild;
		}

		private bool WithinRadius {
			get {
				return (bool) withinRadius.IsChecked;
			}
		}

		private void Rebuild () {
			visibleSequences.Clear();
			Refresh();
		}

		private void Refresh () {
			ILinearDomain referenceGene = map.Model.ReferenceSequence;

			queryNameField.Text = referenceGene == null
			? "Unavailable"
			: string.Format( "{0} {1}", referenceGene.Label, referenceGene.Name );

			lock ( visibleSequences ) {
				List<SequenceSummary> itemsToRemove = new List<SequenceSummary>();

				foreach ( SequenceSummary g in visibleSequences ) {
					if ( WithinRadius && g.DistanceFromReferenceSequence > map.View.Threshold ) {
						itemsToRemove.Add( g );
					}
				}

				foreach ( SequenceSummary g in itemsToRemove ) {
					visibleSequences.Remove( g );
				}

				foreach ( SequenceSummary summary in map.Model.SequenceSummaries ) {
					if ( !WithinRadius || summary.DistanceFromReferenceSequence <= map.View.Threshold ) {
						if ( !visibleSequences.Contains( summary ) ) {
							visibleSequences.Add( summary );
						}
					}
				}

			}
		}

		private void CheckMarkedRows () {
			foreach ( SequenceSummary summary in geneDetails.SelectedItems ) {
				summary.Selected = true;
			}
		}

		private void UncheckMarkedRows () {
			foreach ( SequenceSummary summary in geneDetails.SelectedItems ) {
				summary.Selected = false;
			}
		}

		private void CentreOnSelection () {
			SequenceSummary selectedItem = (SequenceSummary) this.geneDetails.SelectedItem;

			if ( selectedItem != null ) {
				map.Model.ReferenceSequence = selectedItem.Sequence;
			}
		}

		private void showSequence_Click ( object sender, RoutedEventArgs e ) {
			SequenceSummary selectedItem = (SequenceSummary) this.geneDetails.SelectedItem;

			if ( selectedItem != null ) {
				map.NavigateToSequence( selectedItem.Sequence );
			}
		}
	}
}
